import logging
from typing import List, Optional, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from core.user_context import UserContext
from modules.system.services.data_permission_service import DataPermissionRuleService, RoleDataPermissionService
from .base import HANDLER_REGISTRY
from utils.log_util import logger

async def apply_permission(db: AsyncSession, table_name: str, user_context: UserContext) -> str:
    """
    应用数据权限规则，生成最终的SQL WHERE条件。
    """
    # 1. 检查用户角色，若无角色则默认无权限
    if not user_context.role_ids:
        logger.warning("[权限引擎] 用户无角色，返回 '1=0' (无权限)")
        return "1=0"

    # 2. 获取用户所有角色对应的、针对特定表的所有有效权限规则
    all_rules = await _get_user_permission_rules(db, user_context.role_ids, table_name)
    if not all_rules:
        logger.info(f"[权限引擎] 未找到针对表 '{table_name}' 的有效权限规则，返回 '1=1' (不限制)")
        return "1=1"

    # 3. 构建权限计算所需的用户信息
    user_info = _build_user_info(user_context)

    # 4. 根据规则生成SQL条件
    conditions = _generate_sql_conditions(all_rules, table_name, user_info)

    # 5. 组合最终的SQL查询条件
    if not conditions:
        logger.warning(f"[权限引擎] 所有规则都未能生成有效SQL条件，返回 '1=0' (无权限)")
        return "1=0"

    # 5. 根据logical_operator对规则进行分组
    # 注意：这里假设每个规则独立应用，或者一组规则共享一个操作符。
    # 如果一个角色有多个规则，它们将根据各自的`logical_operator`来组合。
    # 实际场景可能更复杂，例如，如何组合来自不同角色的具有不同操作符的规则。
    # 当前实现：简单地将所有AND条件的规则组合，所有OR条件的规则组合，然后用OR连接这两组。
    # 这是一个常见的默认行为：满足所有AND条件 *或者* 满足任何一个OR条件。

    and_conditions = [cond for rule, cond in zip(all_rules, conditions) if rule.logical_operator == 'AND']
    or_conditions = [cond for rule, cond in zip(all_rules, conditions) if rule.logical_operator != 'AND'] # 默认或显式OR

    final_and_part = " AND ".join(f"({c})" for c in and_conditions) if and_conditions else ""
    final_or_part = " OR ".join(f"({c})" for c in or_conditions) if or_conditions else ""

    # 组合AND和OR部分
    if final_and_part and final_or_part:
        final_condition = f"(({final_and_part}) OR ({final_or_part}))"
    elif final_and_part:
        final_condition = final_and_part
    elif final_or_part:
        final_condition = final_or_part
    else:
        # 理论上不会发生，因为我们已经检查了conditions非空
        return "1=0"

    logger.info(f"[权限引擎] 应用于表 '{table_name}' 的最终权限条件: {final_condition}")
    return final_condition


async def _get_user_permission_rules(
    db: AsyncSession, 
    role_ids: List[int], 
    table_name: str
) -> List[Dict[str, Any]]:
    """获取用户所有角色下，针对特定表的所有有效权限规则。"""
    try:
        # 一次性获取所有角色关联的规则
        all_role_rules = await RoleDataPermissionService.get_role_rules(db, role_ids)
        
        # 过滤出针对当前表的规则
        table_rules = [rule for rule in all_role_rules if rule.table_name == table_name]
        
        logger.info(f"[权限引擎] 角色ID {role_ids} 共找到 {len(table_rules)} 条针对表 '{table_name}' 的规则")
        return table_rules
    except Exception as e:
        logger.error(f"[权限引擎] 获取角色 {role_ids} 的权限规则时发生错误: {e}")
        return []


def _build_user_info(user_context: UserContext) -> Dict[str, Any]:
    """构建权限计算所需的用户信息字典。"""
    user_info = {
        "department": user_context.department,
        "user_id": user_context.uid,
        "username": user_context.username,
        "name": user_context.name,
        "dept_ids": user_context.dept_codes
    }
    
    return user_info


def _generate_sql_conditions(
    rules: List[Dict[str, Any]], 
    table_name: str, 
    user_info: Dict[str, Any]
) -> List[str]:
    """遍历规则列表，调用处理器生成SQL条件。"""
    conditions = []
    for rule in rules:
        handler = HANDLER_REGISTRY.get(rule.condition_type)
        if not handler:
            logger.warning(f"[权限引擎] 未找到规则 '{rule.name}' 的处理器: {rule.condition_type}")
            continue
        try:
            cond = handler.generate_sql(table_name, rule.config_json, user_info)
            if cond and cond.strip() and cond not in ("1=1", "1=0"):
                conditions.append(f"({cond})")
            elif cond == "1=0":
                logger.warning(f"[权限引擎] 规则 '{rule.name}' 生成了 '1=0' (无权限) 条件，已忽略")
            else:
                logger.info(f"[权限引擎] 规则 '{rule.name}' 生成了 '1=1' (全权限) 或无效条件，已忽略")
        except Exception as e:
            logger.error(f"[权限引擎] 处理规则 '{rule.name}' 时发生错误: {e}")
            continue
    return conditions
    